const transactionDao = require("../common/dao/transaction");
const configDao = require("../common/dao/bancor_config");
const bancorDao = require("../common/dao/bancor");
const transferDao = require("../common/dao/transfer");   // bancor 同步专用
const transferDao2 = require("../common/dao/transfer2"); // erc20token 专用

const bancorCurrencyDao = require("../common/dao/bancor_currency");

const InputDataDecoder = require('ethereum-input-data-decoder');
const configWeb3 = require('../config/web3');
const ethers = require('ethers');
let provider = new ethers.providers.JsonRpcProvider(configWeb3.provider);

module.exports = {
    async bancor() {
        try {
            if (global.bancor_syn === 1) {
                console.log("ready bancor_syn");
                return;
            }
            global.bancor_syn = 1;

            let config = await configDao.configList({id: 1});
            let blockNum_from = config[0].blockNum;
            let blockNum_to = await provider.getBlockNumber();
            console.log("bancor:---" + blockNum_to);

            let currencyList = await bancorCurrencyDao.currencyList({});
            let isBancorNetworkList = await bancorNetwork(blockNum_from, blockNum_to); // 如果不存在数据，跳过
            let isBancorConvertList = await bancorConvert(blockNum_from, blockNum_to, currencyList);
            if (!isBancorNetworkList && !isBancorConvertList) {
                global.bancor_syn = 0;
                return;
            }

            await SmartTokenTransfer(blockNum_from, blockNum_to, currencyList);
            await EtherTokenTransfer(blockNum_from, blockNum_to);

            await configDao.configUpdate({
                id: 1
            }, {
                blockNum: blockNum_to
            });

            global.bancor_syn = 0;
        } catch (e) {
            console.log(e);

            global.bancor_syn = 0;
        }
    },

    async transfer() {
        try {
            if (global.transfer_syn === 1) {
                console.log("ready transfer_syn");
                return;
            }
            global.transfer_syn = 1;

            let config = await configDao.configList({id: 1});
            let blockNum_from = config[0].transferNum;
            let blockNum_to = await provider.getBlockNumber();
            console.log("transfer:---" + blockNum_to);

            let currencyList = await bancorCurrencyDao.currencyList({});

            await SmTransfer(blockNum_from, blockNum_to, currencyList);

            await configDao.configUpdate({
                id: 1
            }, {
                transferNum: blockNum_to
            });

            global.transfer_syn = 0;
        } catch (e) {
            console.log(e);

            global.transfer_syn = 0;
        }
    }
};

// 1.同步bancorNetwork 买入列表
async function bancorNetwork(blockNum_from, blockNum_to) {
    let bancorNetwork = "0x9A386A9B90B8CCdcc57662cd56d7067c1F45026D";
    let condition = {
        to: bancorNetwork,
        start: blockNum_from,
        end: blockNum_to,
        status: 1
    };
    let list = await transactionDao.transactionList(condition);
    if (list.length == 0) {
        console.log("no bancorNetwork transactionList")
        return 0;
    }
    let decoder = new InputDataDecoder(configWeb3.abi.BancorNetwork);
    for (let i in list) {
        let info = decoder.decodeData(list[i].data);
        if (info.name == 'convertFor') {
            let obj = {
                to: "0x" + info.inputs[0][1],
                value: info.inputs[1].toString(),
                txHash: list[i].transactionHash,
                from: list[i].from,
                amount: 0,
                timestamp: list[i].timestamp,
            };
            bancorDao.bancorAdd(obj);
        }
    }
    return 1;
}

// 2.同步所有的convert 卖出列表
async function bancorConvert(blockNum_from, blockNum_to, currencyList) {
    let l = 0;
    for (let j in currencyList) {
        let bancorConvert = currencyList[j].bcv_address;
        let condition = {
            to: bancorConvert,
            start: blockNum_from,
            end: blockNum_to,
            status: 1
        };
        let list = await transactionDao.transactionList(condition);
        if (list.length == 0) {
            l++;
            if(l == currencyList.length){
                console.log("no bancorConvert transactionList");
                return 0;
            }
        }
        let decoder = new InputDataDecoder(configWeb3.abi.BancorConverter);
        for (let i in list) {
            let info = decoder.decodeData(list[i].data);
            if (info.name == 'convert') {
                let obj = {
                    to: "0x" + info.inputs[0],
                    value: 0,
                    txHash: list[i].transactionHash,
                    from: list[i].from,
                    amount: info.inputs[2].toString(),
                    timestamp: list[i].timestamp,
                };
                bancorDao.bancorAdd(obj);
            }
        }
    }
    return 1;
}

// 3.同步所有的smartToken event
async function SmartTokenTransfer(blockNum_from, blockNum_to, currencyList) {
    for (let j in currencyList) {
        let SmartTokenAddress = currencyList[j].contract_address;
        let topic = ethers.utils.id("Transfer(address,address,uint256)");
        let filter = {
            address: SmartTokenAddress,
            fromBlock: blockNum_from + 1,
            toBlock: blockNum_to,
            topics: [topic]
        };
        let result = await provider.getLogs(filter);
        let abiCode = new ethers.utils.Interface(configWeb3.abi.SmartToken);
        for (let i in result) {
            let res = abiCode.parseLog({data: result[i].data, topics: result[i].topics});
            let obj = {
                txHash: result[i].transactionHash,
                from: res.values._from,
                to: res.values._to,
                amount: res.values._value.toString(),
                contract: SmartTokenAddress,
                blockNumber: result[i].blockNumber
            };
            if (obj.to != configWeb3.address.BancorNetwork) {
                transferDao.transferAdd(obj);
            }
        }
    }
}

// 4.同步所有的etherToken event
async function EtherTokenTransfer(blockNum_from, blockNum_to) {
    let contractAddress = configWeb3.address.EtherToken;
    let topic = ethers.utils.id("Transfer(address,address,uint256)");
    let filter = {
        address: contractAddress,
        fromBlock: blockNum_from + 1,
        toBlock: blockNum_to,
        topics: [topic]
    };
    let result = await provider.getLogs(filter);
    let abiCode = new ethers.utils.Interface(configWeb3.abi.EtherToken);
    for (let i in result) {
        let res = abiCode.parseLog({data: result[i].data, topics: result[i].topics});
        let obj = {
            txHash: result[i].transactionHash,
            from: res.values._from,
            to: res.values._to,
            amount: res.values._value.toString(),
            contract: contractAddress,
            blockNumber: result[i].blockNumber
        };
        if (obj.to == configWeb3.address.BancorNetwork) {
            transferDao.transferAdd(obj);
        }
    }
}

// 5.同步所有的smartToken event --- transfer 转账专用
async function SmTransfer(blockNum_from, blockNum_to, currencyList) {
    for (let j in currencyList) {
        let SmartTokenAddress = currencyList[j].contract_address;
        let topic = ethers.utils.id("Transfer(address,address,uint256)");
        let filter = {
            address: SmartTokenAddress,
            fromBlock: blockNum_from + 1,
            toBlock: blockNum_to,
            topics: [topic]
        };
        let result = await provider.getLogs(filter);
        let abiCode = new ethers.utils.Interface(configWeb3.abi.SmartToken);
        for (let i in result) {
            let res = abiCode.parseLog({data: result[i].data, topics: result[i].topics});
            let obj = {
                txHash: result[i].transactionHash,
                from: res.values._from,
                to: res.values._to,
                amount: res.values._value.toString(),
                contract: SmartTokenAddress,
                blockNumber: result[i].blockNumber
            };
            if (obj.to != configWeb3.address.BancorNetwork) {
                transferDao2.transferAdd(obj);
            }
        }
    }
}

